
/* = Includes =============================================================== */
#include <util/common_macros.h>
#include <util/mem.h>
#include <util/math_macros.h>

#include "../dsp/filters/filters.h"
#include "../dsp/dsp.h"

#include "image.h"

/* ========================================================================== */
int imp_image_get_stride(int width, ImpImageType type) {
	switch (type) {
		case IMP_IMAGE_TYPE_GRAY:
			return width;
			break;
		case IMP_IMAGE_TYPE_RGB:
			return width * 3;
			break;
	}
	return -1;
}

void imp_image_clear(ImpImage * Img) {
	long int r;
	for (r = 0; r < Img->nbytes; r++) {
		Img->data[r] = 0;
	}
}

void imp_image_copy(ImpImage * Img, ImpImage ** Copy) {

	_exit_if_fail(Copy);

	if (*Copy == NULL) (*Copy) = imp_image_new(Img->width, Img->height, Img->type);

	int i;
	for (i = 0; i < Img->nbytes; i++) {
		(*Copy)->data[i] = Img->data[i];
	}

}

/* ========================================================================== */
void imp_image_mat2gray(ImpMatrix * Mat, ImpImage ** Gray) {
	int i;
	unsigned char px;
	_exit_if_fail(Gray);
	if (*Gray == NULL) (*Gray) = imp_image_new(Mat->columns, Mat->rows, IMP_IMAGE_TYPE_GRAY);

	for (i = 0; i < Mat->size; i++) {
		px = (unsigned char) Mat->data[i];

		px = CLAMP(px, 0, 255);

		(*Gray)->data[i] = px;
	}
}

void imp_image_mat2rgb(ImpMatrix * Mat, ImpImage ** RGB) {
	int i;
	unsigned char px;

	_exit_if_fail(RGB);

	if (*RGB == NULL) (*RGB) = imp_image_new(Mat->columns, Mat->rows, IMP_IMAGE_TYPE_RGB);

	unsigned char * rgb = (*RGB)->data;

	for (i = 0; i < Mat->size; i++) {
		px = (unsigned char) Mat->data[i];

		px = CLAMP(px, 0, 255);

		*rgb = px;
		rgb++;
		*rgb = px;
		rgb++;
		*rgb = px;
		rgb++;

	}
}

void imp_image_gray2mat(ImpImage * Gray, ImpMatrix ** Mat) {
	int i;

	_exit_if_fail(Mat);
	if (*Mat == NULL) (*Mat) = imp_matrix_new(Gray->height, Gray->width);

	for (i = 0; i < Gray->npixels; i++) {
		(*Mat)->data[i] = (real) Gray->data[i];
	}
}

void imp_image_rgb2gray(ImpImage * RGB, ImpImage ** Gray) {

	real px;

	unsigned char * rgb_data;
	unsigned char * gray_data;

	_exit_if_fail(Gray);
	if (*Gray == NULL) (*Gray) = imp_image_new(RGB->width, RGB->height, IMP_IMAGE_TYPE_GRAY);

	rgb_data = RGB->data;
	gray_data = (*Gray)->data;

	int i;
	for (i = 0; i < RGB->npixels; i++) {
		/* Matlab coeficients */
		px = 0.2989 * (*rgb_data++);
		px += 0.5870 * (*rgb_data++);
		px += 0.1140 * (*rgb_data++);

		/* Others coeficients */
		//px = 0.2125 * (*rgb_data++);
		//px += 0.7154 * (*rgb_data++);
		//px += 0.0721 * (*rgb_data++);

		px = ROUND(px);

		px = CLAMP(px, 0.0, 255.0);

		*gray_data = (unsigned char) px;
		gray_data++;
	}
}

void imp_image_gray2rgb(ImpImage * Gray, ImpImage ** RGB) {

	int i;
	unsigned char * rgb_data;
	unsigned char * gray_data;

	_exit_if_fail(RGB);
	if (*RGB == NULL) (*RGB) = imp_image_new(Gray->width, Gray->height, IMP_IMAGE_TYPE_RGB);

	gray_data = Gray->data;
	rgb_data = (*RGB)->data;

	for (i = 0; i < Gray->npixels; i++) {
		*rgb_data = *gray_data;
		rgb_data++;

		*rgb_data = *gray_data;
		rgb_data++;

		*rgb_data = *gray_data;
		rgb_data++;

		gray_data++;
	}
}

/* ========================================================================== */

void imp_image_blur(ImpMatrix * Mat, int w) {
	ImpMatrix * Gauss = NULL;
	Gauss = imp_filter_new_gaussian(w, w / 4.0);
	
	ImpMatrix * MatConv = NULL;
	imp_dsp_conv(Mat, Gauss, &MatConv);
	
	imp_matrix_copy(MatConv, &Mat);
	
	imp_object_delete(Gauss);
	imp_object_delete(MatConv);

}
